import React, { Component } from 'react';
import { Card, Table, Tag, Button, Popconfirm, message, Drawer, Space, Spin, Tree, Tooltip, Input } from 'antd';
import { PlusOutlined, CopyOutlined, ImportOutlined, ExclamationCircleFilled } from '@ant-design/icons';
import { connect } from 'dva';
import { filterAuth } from "@/support/common";
import EditModal from './editModal';
import AddModal from './addModal';
import ProDescriptions from '@ant-design/pro-descriptions';
import styles from './style.less';

const { TextArea } = Input;
const { TreeNode } = Tree;
const itemTypes = {
  0: { value: '菜单', color: '#1890ff' },
  2: { value: '按钮', color: '#52c41a' },
  1: { value: '页面', color: '#f5222d' },
};
const mapStateToProps = (state) => ({
  menu: state.menu,
  resource: state.resource,
  loading: state.loading.effects['resource/getData'],
  copyLoading: state.loading.effects['resource/postObj'],
}
);

class ResourceList extends Component<any, any> {
  state = {
    data: [],
    addModalVisible: false,
    modalVisible: false,
    formData: null,
    record: {},
    rootId: '', //根节点id
    copyVisible: false,
    checkedKeys: [],
    expandedKeys: [],
    jsonStr: null,
    importVisible: false,
    importJson: undefined
  };

  componentDidMount() {
    this.flushData();
  }

  flushData = () => {
    const { dispatch } = this.props;

    dispatch({
      type: "resource/getData",
      payload: { url: "/resource/findmenutree" },
      callback: (res) => {
        if (res.statusCode == "0" && res.data && res.data[0] && res.data[0].resourceParent) {
          this.setState({ rootId: res.data[0].resourceParent, data: res.data });
        }
      }
    });
  }

  changeModalVisible = (flag, record) => {
    this.setState({
      modalVisible: flag,
      formData: record,
    })
  }

  changeAddModal = (flag, record) => {
    this.setState({
      addModalVisible: flag,
      record: record
    });
  }

  closeAddModal = () => {
    this.setState({
      addModalVisible: false
    });
    this.flushData();
  }

  closeModal = () => {
    this.setState({
      modalVisible: false,
      formData: null,
    })
  }
  handleAdd = () => {
    const { rootId } = this.state;
    this.setState({ addModalVisible: true, record: { sid: rootId, resourceLevel: 0 } });
  }
  handleDel = (sid) => {
    const { dispatch } = this.props;
    dispatch({
      type: "resource/postObjWithRes",
      payload: { url: "/resource/delete?sid=" + sid },
      callback: (response) => {
        if (response.statusCode == '0') {
          message.success('删除成功');
          this.flushData();
        }
      }
    });
  }
  handleMove = (sid, type) => {
    const { dispatch } = this.props;
    dispatch({
      type: "resource/postObjWithRes",
      payload: { url: "/resource/editsort", sid, type, },
      callback: (response) => {
        if (response.statusCode == '0') {
          message.success('操作成功');
          this.flushData();
        }
      }
    });
  }
  handleBtnEdit = (record) => {
    this.setState({
      modalVisible: true,
      formData: record,
    })
  }

  handleBtnDel = (record) => {
    const sid = record.sid;
    const rCode = record.resourceCode;
    // 查看按钮不能直接删除，可以操作栏的删除功能
    if (rCode && rCode.includes('_show')) {
      message.warn("查看按钮不能直接删除，可以使用操作栏的删除功能！");
      return;
    }
    const { dispatch } = this.props;
    dispatch({
      type: "resource/postObjWithRes",
      payload: { url: "/resource/delete?sid=" + sid },
      callback: (response) => {
        message.success('删除成功');
        this.flushData();
      }
    });
  }
  openImport = () => {
    this.setState({ importVisible: true });
  }

  closeImport = () => {
    this.setState({ importVisible: false, importJson: undefined });
  }

  onImportSubmit = () => {
    const { dispatch } = this.props;
    const { importJson } = this.state;
    if (!this.isJson(importJson)) {
      message.warn("JSON格式不正确，请检查！");
      return;
    }
    if (importJson != undefined) {
      dispatch({
        type: 'resource/postObj',
        payload: {
          url: "/resource/insertbatch",
          list: JSON.parse(importJson)
        },
        callback: (res: any) => {
          message.success('导入成功');
          this.closeImport();
          this.flushData();
        },
      });
    }
  }

  openCopy = () => {
    this.setState({ copyVisible: true });
  }

  closeCopy = () => {
    this.setState({ copyVisible: false, expandedKeys: [], checkedKeys: [], jsonStr: null });
  }

  onCopySubmit = () => {
    const { dispatch } = this.props;
    const { checkedKeys } = this.state;
    if (checkedKeys.length < 1) {
      message.warn("请先选择需要复制的节点！");
      return;
    }
    dispatch({
      type: 'resource/postObj',
      payload: {
        url: "/resource/findcopy",
        sids: checkedKeys
      },
      callback: (res: any) => {
        this.copyJson(JSON.stringify(res.data));
        this.setState({ jsonStr: JSON.stringify(res.data) });
      },
    });
  }

  onCheck = (checkedKeys: any) => {
    this.setState({ checkedKeys: checkedKeys.checked });
  }

  renderTreeNodes = (data: any) => {
    return (
      data &&
      data.map((item: any) => {
        if ((item.children && item.children.length > 0) || (item.buttonChildren && item.buttonChildren.length > 0)) {
          return (
            <TreeNode
              title={
                <Tag
                  style={{ marginRight: 0 }}
                  color={
                    typeof item.resourceType === 'number' && itemTypes[item.resourceType].color
                  }
                >
                  {item.resourceName}
                </Tag>
              }
              key={item.sid}
            >
              {item.children && item.children.length > 0 ? this.renderTreeNodes(item.children) : null}
              {item.buttonChildren && item.buttonChildren.length > 0 ? this.renderTreeNodes(item.buttonChildren) : null}
            </TreeNode>
          );
        }
        return (
          <TreeNode
            key={item.sid}
            title={
              <Tag
                style={{ marginRight: 0 }}
                color={
                  typeof item.resourceType == 'number' && itemTypes[item.resourceType].color
                }
              >
                {item.resourceName}
              </Tag>
            }
          />
        );
      })
    );
  };

  copyJson = (jsonStr: any) => {
    if (navigator.clipboard) {
      navigator.clipboard.writeText(jsonStr);
      message.success("复制成功");
    }
  }

  isJson = (str: any) => {
    if (typeof str == 'string') {
      try {
        let obj = JSON.parse(str);
        if (typeof obj == 'object' && obj) {
          return true;
        } else {
          return false;
        }
      } catch (e) {
        return false;
      }
    }
    return false;
  }

  render() {
    const { addModalVisible, modalVisible, formData, record,
      copyVisible, expandedKeys, checkedKeys, data, jsonStr,
      importVisible, importJson } = this.state;
    const { menu: { permissions }, location: { pathname = '/' }, copyLoading, loading } = this.props;
    const columns = [
      {
        title: '菜单名称',
        dataIndex: 'resourceName',
        fixed: 'left',
        render: (text, record) => {
          if (record.resourceType === 0) {
            return <span><Tag color="#2db7f5">菜单</Tag>{text}</span>;
          } else if (record.resourceType === 1) {
            return <span><Tag color="#f50">页面</Tag>{text}</span>;
          } else {
            return '';
          }
        }
      },
      {
        title: '下级功能清单',
        dataIndex: 'resourceType',
        render: (text, record) => {
          if (record.buttonChildren !== null) {
            return record.buttonChildren.map((d, index) => {
              return (
                <span key={index}>
                  <Popconfirm
                    arrowPointAtCenter={true}
                    title="编辑或删除该按钮?"
                    onConfirm={() => this.handleBtnDel(d)}
                    onCancel={() => this.handleBtnEdit(d)}
                    okText="删除"
                    cancelText="编辑"
                    okButtonProps={{ type: 'danger', size: 'small' }}
                    cancelButtonProps={{ type: 'primary', size: 'small' }}
                  >
                    <Tag style={{ marginBottom: 3, cursor: 'pointer' }} key={d.sid} color="#87d068">{d.resourceName}</Tag>
                  </Popconfirm>
                </span>)
            })
          } else if (record.resourceLevel === 1 && record.children) {
            return record.children.map((d, index) => {
              return <span key={index}><Tag style={{ marginBottom: 3 }} key={d.sid} color="purple">{d.resourceName}</Tag></span>
            })
          } else {
            return '';
          }
        }
      },
      {
        title: '操作',
        dataIndex: 'action',
        width: 300,
        fixed: 'right',
        render: (text, record) => {
          return <span>
            {filterAuth("resource_doAdd", permissions, pathname) ?
              <Button style={{ marginRight: 5 }} size="small" ghost type="primary" onClick={() => this.changeAddModal(true, record)}>新增下级</Button> : ''
            }
            {filterAuth("resource_doEdit", permissions, pathname) ?
              <Button style={{ marginRight: 5 }} size="small" ghost type="primary" onClick={() => this.changeModalVisible(true, record)}>编辑</Button> : ''
            }
            {filterAuth("resource_doDel", permissions, pathname) ?
              <Popconfirm
                title="是否确认删除菜单或资源?"
                onConfirm={() => this.handleDel(record.sid)}
                okText="是"
                cancelText="否"
              >
                <Button style={{ marginRight: 5 }} size="small" ghost type="primary">删除</Button>
              </Popconfirm> : ''
            }
            {filterAuth("resource_doSort", permissions, pathname) && record.showUp ?
              <Popconfirm
                title="是否确认上移菜单?"
                onConfirm={() => this.handleMove(record.sid, "up")}
                okText="是"
                cancelText="否"
              >
                <Button style={{ marginRight: 5 }} size="small" ghost type="primary">上移</Button>
              </Popconfirm>
              : ''}
            {filterAuth("resource_doSort", permissions, pathname) && record.showDown ?
              <Popconfirm
                title="是否确认下移菜单?"
                onConfirm={() => this.handleMove(record.sid, "down")}
                okText="是"
                cancelText="否"
              >
                <Button size="small" ghost type="primary">下移</Button>
              </Popconfirm>
              : ''}
          </span>
        }
      },
    ];
    return (
      <Card
        title=""
        bordered={false}
      >
        <div className="my_newItem">
          {
            filterAuth("resource_doAdd", permissions, pathname) ? (
              <Button size="small" icon={<PlusOutlined />} type="primary" onClick={this.handleAdd} >新增一级菜单</Button>
            ) : null
          }
          {
            filterAuth("resource_doCopy", permissions, pathname) ? (
              <Button size="small" icon={<CopyOutlined />} type="primary" onClick={this.openCopy} >复制菜单</Button>
            ) : null
          }
          {
            filterAuth("resource_doJson", permissions, pathname) ? (
              <Button size="small" icon={<ImportOutlined />} type="primary" onClick={this.openImport} >导入菜单</Button>
            ) : null
          }
        </div>
        <Table
          loading={loading}
          rowKey={record => record.sid}
          columns={columns}
          size="small"
          pagination={false}
          scroll={{ x: 'max-content' }}
          dataSource={data}
        />
        {formData ?
          <EditModal
            modalVisible={modalVisible}
            formData={formData}
            flushData={this.flushData}
            dispatch={this.props.dispatch}
            closeModal={this.closeModal}
          />
          : null
        }
        <AddModal
          modalVisible={addModalVisible}
          record={record}
          dispatch={this.props.dispatch}
          closeModal={this.closeAddModal}
        />
        <Drawer
          title={<>复制菜单<Tooltip placement="bottom" title="勾选父节点不会自动勾选子节点"><ExclamationCircleFilled style={{ marginLeft: 4, transform: 'translateY(-15%)', fontSize: 12, color: 'orange' }} /></Tooltip></>}
          onClose={this.closeCopy}
          visible={copyVisible}
          closable={false}
          width={500}
          extra={
            <Space>
              <Button size="small" onClick={this.closeCopy}>取消</Button>
              {jsonStr ?
                null
                :
                <Button size="small" loading={copyLoading || loading} onClick={this.onCopySubmit} type="primary">
                  复制
                </Button>
              }
            </Space>
          }
        >
          {jsonStr ?
            <ProDescriptions column={1} className={styles.json}>
              <ProDescriptions.Item valueType="jsonCode">
                {jsonStr}
              </ProDescriptions.Item>
            </ProDescriptions>
            :
            <Spin spinning={loading} style={{ top: 30 }}>
              <Tree
                checkable
                checkStrictly
                onCheck={this.onCheck}
                onExpand={(keys: any) => this.setState({ expandedKeys: keys })}
                expandedKeys={expandedKeys}
                checkedKeys={checkedKeys}
              >
                {this.renderTreeNodes(data)}
              </Tree>
            </Spin>
          }
        </Drawer>
        <Drawer
          title='导入菜单'
          onClose={this.closeImport}
          visible={importVisible}
          closable={false}
          width={500}
          extra={
            <Space>
              <Button size="small" onClick={this.closeImport}>取消</Button>
              <Button size="small" loading={copyLoading} onClick={this.onImportSubmit} type="primary">
                导入
              </Button>
            </Space>
          }
        >
          <div style={{ height: '100%' }}>
            <TextArea
              autoSize={{ minRows: 22 }}
              onChange={(e: any) => this.setState({ importJson: e.target.value })}
              value={importJson}
              showCount
              placeholder="请输入JSON格式字符串"
            />
          </div>
        </Drawer>
      </Card>
    )
  }
}

export default connect(mapStateToProps)(ResourceList);

